#include "converter.h"
#include "../../semantics/visitordata.h"
#include "../../semantics/classsemantic.h"
#include "../../semantics/error.h"

void  ConverterNode::write(GraphStream * s)
{
	this->accept(s);
	const char * typet="procedure";
	if (this->m_type==CT_QUERY)
		typet="query";
	fprintf(s->stream,"\tnode_%d [label=\"(%d,%d)\\nConverter %s \\\"%s\\\"\" shape=\"rectangle\"]\n",this->number(),this->line(),this->position(),typet,this->m_featurename->c_str());
	m_parameters->write(s);
	fprintf(s->stream,"\tnode_%d -> node_%d\n",this->number(),m_parameters->number());
}


void ConverterNode::createConverter(ParentData * parent)
{
  bool errorsig=false;
  bool error=false;
  if (m_parameters)
  {
	 if (m_parameters->vector().size()==1)
	 {
		 if (parent->Classes->getClassByName(m_parameters->vector()[0])==NULL)
		 {
			 error=true;
			 parent->Classes->add(new TypeDoesNotExists(m_parameters->vector()[0]));
		 }
	 } else errorsig=true;
  } else errorsig=true;
  if (errorsig)
	  parent->Classes->add(new IncorrectConverterSignature(this));
  
  //Exit if found error
  if (errorsig||error)
	  return;
  parent->CurrentMethod=parent->CurrentClass->getMethodByName(featureName());
  if (parent->CurrentMethod==NULL)
  {
	  parent->Classes->add(new MethodDoesNotExists(this));
	  return;
  }

  if (this->type()==CT_PROCEDURE)
	  createProcedure(parent);
  else
	  createQuery(parent);
}

void ConverterNode::createProcedure(ParentData * parent)
{
	std::vector<std::string> signature;
	signature.push_back(params()->vector()[0]->fullName());
	if (parent->CurrentMethod->hasFormalArgSignature(signature,parent->CurrentClass->cnode()->name())
		&& parent->CurrentMethod->returnType()==NULL	
	   )
	{
		if (parent->CurrentClass->getConstructorByMethodName(featureName()))
		{
		 if (parent->CurrentClass->addConvertFrom(params()->vector()[0]->fullName(),featureName())==false)
			parent->Classes->add(new ConverterAlreadyDefined(this));
		}
		else parent->Classes->add(new ConverterIsNotConstructor(this));
	}
	else parent->Classes->add(new NotEqualSignatureForConverter(this));
}
void ConverterNode::createQuery(ParentData * parent)
{
	std::vector<std::string> signature;
	bool error=parent->CurrentMethod->hasFormalArgSignature(signature,parent->CurrentClass->cnode()->name());
	ClassTypeNode * node=parent->CurrentMethod->returnType();
	if (node!=NULL)
	{
		error=error && node->fullName()!=params()->vector()[0]->fullName();
	}
	else error=true;
	if (error==false)
	{
		if (parent->CurrentClass->addConvertTo(params()->vector()[0]->fullName(),featureName())==false)
			parent->Classes->add(new ConverterAlreadyDefined(this));
	}
	else parent->Classes->add(new NotEqualSignatureForConverter(this));
}